package org.rsbot.gui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Rectangle;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import javax.swing.AbstractListModel;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JTextPane;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import org.rsbot.log.LogFormatter;
import org.rsbot.util.GlobalConfiguration;
import org.rsbot.util.GlobalConfiguration.OperatingSystem;
import org.rsbot.util.StringUtil;

public class LogTextArea extends JList
{
  public static final int MAX_ENTRIES = 100;
  public static final Rectangle BOTTOM_OF_WINDOW = new Rectangle(0, 2147483647, 0, 0);
  private static final long serialVersionUID = 0L;
  private final LogQueue logQueue = new LogQueue(null);

  private final LogAreaListModel model = new LogAreaListModel(null);

  private final Runnable scrollToBottom = new Runnable() {
    public void run() {
      LogTextArea.this.scrollRectToVisible(LogTextArea.BOTTOM_OF_WINDOW);
    }
  };

  private static final Formatter formatter = new Formatter() {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss");

    public String format(LogRecord paramLogRecord)
    {
      String[] arrayOfString = paramLogRecord.getLoggerName().split("\\.");
      String str = arrayOfString[(arrayOfString.length - 1)];

      return String.format("[%s] %-16s %s %s", new Object[] { this.dateFormat.format(Long.valueOf(paramLogRecord.getMillis())), str.length() > 16 ? str.substring(0, 16 - "...".length()) + "..." : str, paramLogRecord.getMessage(), StringUtil.throwableToString(paramLogRecord.getThrown()) });
    }
  };

  private static final Formatter copyPasteFormatter = new LogFormatter(false);

  public LogTextArea()
  {
    setModel(this.model);
    setCellRenderer(new Renderer(null));
    setSelectionMode(2);
    if (GlobalConfiguration.getCurrentOperatingSystem() == GlobalConfiguration.OperatingSystem.MAC)
      setFont(new Font("Monaco", 0, 10));
    else {
      setFont(new Font("Monospaced", 0, 12));
    }

    new Thread(this.logQueue, "LogGuiQueue").start();
  }

  public void log(LogRecord paramLogRecord)
  {
    this.logQueue.queue(new WrappedLogRecord(paramLogRecord));
  }

  private class WrappedLogRecord
  {
    public final LogRecord record;
    public final String formatted;

    public WrappedLogRecord(LogRecord arg2)
    {
      LogRecord localLogRecord;
      this.record = localLogRecord;
      this.formatted = LogTextArea.formatter.format(localLogRecord);
    }

    public String toString()
    {
      return LogTextArea.copyPasteFormatter.format(this.record);
    }
  }

  private static class Renderer
    implements ListCellRenderer
  {
    private final Border EMPTY_BORDER = new EmptyBorder(1, 1, 1, 1);
    private final Border SELECTED_BORDER = UIManager.getBorder("List.focusCellHighlightBorder");

    private final Color DARK_GREEN = new Color(0, 90, 0);

    public Component getListCellRendererComponent(JList paramJList, Object paramObject, int paramInt, boolean paramBoolean1, boolean paramBoolean2)
    {
      if (!(paramObject instanceof LogTextArea.WrappedLogRecord))
        return new JLabel();
      LogTextArea.WrappedLogRecord localWrappedLogRecord = (LogTextArea.WrappedLogRecord)paramObject;

      JTextPane localJTextPane = new JTextPane();
      localJTextPane.setDragEnabled(true);
      localJTextPane.setText(localWrappedLogRecord.formatted);
      localJTextPane.setComponentOrientation(paramJList.getComponentOrientation());
      localJTextPane.setFont(paramJList.getFont());
      localJTextPane.setBorder((paramBoolean2) || (paramBoolean1) ? this.SELECTED_BORDER : this.EMPTY_BORDER);

      localJTextPane.setForeground(Color.DARK_GRAY);
      localJTextPane.setBackground(Color.WHITE);

      if (localWrappedLogRecord.record.getLevel() == Level.SEVERE) {
        localJTextPane.setBackground(Color.RED);
        localJTextPane.setForeground(Color.WHITE);
      }

      if (localWrappedLogRecord.record.getLevel() == Level.WARNING) {
        localJTextPane.setForeground(Color.RED);
      }

      if ((localWrappedLogRecord.record.getLevel() == Level.FINE) || (localWrappedLogRecord.record.getLevel() == Level.FINER) || (localWrappedLogRecord.record.getLevel() == Level.FINEST))
      {
        localJTextPane.setForeground(this.DARK_GREEN);
      }

      Object[] arrayOfObject1 = localWrappedLogRecord.record.getParameters();
      if (arrayOfObject1 != null) {
        for (Object localObject : arrayOfObject1) {
          if (localObject == null)
          {
            continue;
          }
          if ((localObject instanceof Color))
            localJTextPane.setForeground((Color)localObject);
          else if ((localObject instanceof Font)) {
            localJTextPane.setFont((Font)localObject);
          }
        }
      }

      return localJTextPane;
    }
  }

  private class LogQueue
    implements Runnable
  {
    public static final int FLUSH_RATE = 1000;
    private final Object lock = new Object();

    private List<LogTextArea.WrappedLogRecord> queue = new ArrayList(100);

    private LogQueue() {  }

    public void queue(LogTextArea.WrappedLogRecord paramWrappedLogRecord) { synchronized (this.lock) {
        this.queue.add(paramWrappedLogRecord);
      } }

    public void run()
    {
      while (true) {
        ArrayList localArrayList = null;

        synchronized (this.lock) {
          if (this.queue.size() != 0) {
            localArrayList = new ArrayList(this.queue);
            this.queue = this.queue.subList(0, 0);
          }
        }
        if (localArrayList != null)
        {
          LogTextArea.this.model.addAllElements(localArrayList);
          SwingUtilities.invokeLater(LogTextArea.this.scrollToBottom);
        }
        try {
          Thread.sleep(1000L);
        } catch (InterruptedException localInterruptedException) {
          throw new RuntimeException(localInterruptedException);
        }
      }
    }
  }

  private class LogAreaListModel extends AbstractListModel
  {
    private static final long serialVersionUID = 0L;
    private List<LogTextArea.WrappedLogRecord> records = new ArrayList(100);

    private LogAreaListModel() {
    }
    public void addAllElements(List<LogTextArea.WrappedLogRecord> paramList) { this.records.addAll(paramList);
      if (getSize() > 100) {
        this.records = this.records.subList(getSize() - 100, getSize());

        fireContentsChanged(this, 0, getSize() - 1);
      } else {
        fireIntervalAdded(this, getSize() - 1, getSize() - 1);
      } }

    public Object getElementAt(int paramInt)
    {
      return this.records.get(paramInt);
    }

    public int getSize() {
      return this.records.size();
    }
  }
}